
package framework.core.dao.imp;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import framework.core.dao.IBaseDao;
import framework.core.entity.BaseEntity;
import framework.core.util.SingletonLog;

/**
 * @ClassName: BaseDao 
 * @Description: 基础数据库操作类
 * @author: Ching Wang
 * @date 2013-5-18 下午12:23:30 
 * 
 * @param <T>
 */
@Repository
@SuppressWarnings("unchecked")
public class BaseDao<T extends BaseEntity> implements IBaseDao<T> {

	protected Logger logger = SingletonLog.getSingletonLog();
	@Resource
	protected SessionFactory sessionFactory;

	/* 
	 * (非 Javadoc) 
	 * <p>Title: save</p> 
	 * <p>Description: </p> 
	 * @param entity
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#save(framework.core.entity.BaseEntity)
	 */
	@Override
	public void save(T entity)  throws Exception{

		Assert.notNull(entity, "entity不能为空");
		sessionFactory.getCurrentSession().save(entity);
		logger.debug("save entity: {}", entity);
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: update</p> 
	 * <p>Description: </p> 
	 * @param entity
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#update(framework.core.entity.BaseEntity)
	 */
	@Override
	public void update(T entity)  throws Exception{

		Assert.notNull(entity, "entity不能为空");
		sessionFactory.getCurrentSession().update(entity);
		logger.debug("update entity: {}", entity);
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: delete</p> 
	 * <p>Description: </p> 
	 * @param entity
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#delete(framework.core.entity.BaseEntity)
	 */
	@Override
	public boolean delete(T entity)  throws Exception{

		Assert.notNull(entity, "entity不能为空");
		sessionFactory.getCurrentSession().delete(entity);
		logger.debug("delete entity: {}", entity);
		return true;
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: findAll</p> 
	 * <p>Description: </p> 
	 * @param c
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findAll(java.lang.Class)
	 */
	@Override
	public List<T> findAll(Class<T> c)  throws Exception{

		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
				c);
		return criteria.list();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: findAll</p> 
	 * <p>Description: </p> 
	 * @param c
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findAll(java.lang.Class, int, int)
	 */
	@Override
	public List<T> findAll(Class<T> c, int firstResult, int maxResults)  throws Exception{

		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(c);
		return criteria.setFirstResult(firstResult).setMaxResults(maxResults).list();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: findById</p> 
	 * <p>Description: </p> 
	 * @param c
	 * @param id
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findById(java.lang.Class, java.lang.String)
	 */
	@Override
	public T findById(Class<T> c, String id)  throws Exception{
		return (T) sessionFactory.getCurrentSession().get(c, id);
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: findByCriteria</p> 
	 * <p>Description: </p> 
	 * @param detachedCriteria
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findByCriteria(org.hibernate.criterion.DetachedCriteria)
	 */
	public List<T> findByCriteria(DetachedCriteria detachedCriteria)  throws Exception{

		Criteria criteria = detachedCriteria.getExecutableCriteria(sessionFactory.getCurrentSession());
		return criteria.list();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: findByCriteria</p> 
	 * <p>Description: </p> 
	 * @param detachedCriteria
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findByCriteria(org.hibernate.criterion.DetachedCriteria, int, int)
	 */
	@Override
	public List<T> findByCriteria(DetachedCriteria detachedCriteria, int firstResult, int maxResults)  throws Exception{

		Criteria criteria = detachedCriteria.getExecutableCriteria(sessionFactory.getCurrentSession());
		
		return criteria.setFirstResult(firstResult).setMaxResults(maxResults).list();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: getCount</p> 
	 * <p>Description: </p> 
	 * @param detachedCriteria
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#getCount(org.hibernate.criterion.DetachedCriteria)
	 */
	@Override
	public long getCount(DetachedCriteria detachedCriteria)  throws Exception{

		Criteria criteria = detachedCriteria.getExecutableCriteria(sessionFactory.getCurrentSession());
		long total = Long.parseLong(criteria.setProjection(Projections.rowCount()).uniqueResult().toString());
		criteria.setProjection(null);
		criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		return total;
	}
	
	/*
	 * (非 Javadoc) 
	 * <p>Title: findBySql</p> 
	 * <p>Description: </p> 
	 * @param hql
	 * @param values
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#findBySql(java.lang.String, java.lang.Object[])
	 */
	@Override
	public List<Map<String, Object>> findBySql(String hql, Object[] values)  throws Exception{

		Assert.hasText(hql, "hql不能为空");
		Query query = sessionFactory.getCurrentSession().createSQLQuery(hql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		for (int i = 0; i < values.length; i++) {
			query.setParameter(i, values[i]);
		}
		List<Map<String, Object>> maps = query.list();
		return maps;
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: executeHql</p> 
	 * <p>Description: </p> 
	 * @param hql
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#executeHql(java.lang.String)
	 */
	@Override
	public int executeHql(String hql) throws Exception {
		Assert.hasText(hql, "hql不能为空");
		Query q = sessionFactory.getCurrentSession().createQuery(hql);
		return q.executeUpdate();
	}
	
	/*
	 * (非 Javadoc) 
	 * <p>Title: executeHql</p> 
	 * <p>Description: </p> 
	 * @param hql
	 * @param values
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#executeHql(java.lang.String, java.util.Map)
	 */
	@Override
	public int executeHql(String hql, Map<String, ?> values) throws Exception {
		
		Assert.hasText(hql, "hql不能为空");
		Query query = sessionFactory.getCurrentSession().createQuery(hql);
		if (values != null)
		{
			query.setProperties(values);
		}
		return query.executeUpdate();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: find</p> 
	 * <p>Description: </p> 
	 * @param hql
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#find(java.lang.String)
	 */
	@Override
	public List<T> find(String hql) throws Exception {
		Assert.hasText(hql, "hql不能为空");
		Query q = sessionFactory.getCurrentSession().createQuery(hql);
		return q.list();
	}

	/*
	 * (非 Javadoc) 
	 * <p>Title: find</p> 
	 * <p>Description: </p> 
	 * @param hql
	 * @param params
	 * @return
	 * @throws Exception 
	 * @see framework.core.dao.IBaseDao#find(java.lang.String, java.util.Map)
	 */
	@Override
	public List<T> find(String hql, Map<String, Object> params)
			throws Exception {
		Assert.hasText(hql, "hql不能为空");
		Query q = sessionFactory.getCurrentSession().createQuery(hql);
		if (params != null && !params.isEmpty()) {
			for (String key : params.keySet()) {
				q.setParameter(key, params.get(key));
			}
		}
		return q.list();
	}
}
